package handlers

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"filehive-backend/config"
	"filehive-backend/models"
	"filehive-backend/utils"
)

// FileHandler 文件处理器
type FileHandler struct {
	config config.Config
}

// NewFileHandler 创建文件处理器
func NewFileHandler(cfg config.Config) *FileHandler {
	return &FileHandler{config: cfg}
}

// GetFiles 获取文件列表
func (h *FileHandler) GetFiles(w http.ResponseWriter, r *http.Request) {
	pathParam := r.URL.Query().Get("path")
	
	fullPath, safe := utils.SafePath(h.config.Storage.Path, pathParam)
	if !safe {
		utils.RespondError(w, http.StatusBadRequest, "无效的路径")
		return
	}

	entries, err := os.ReadDir(fullPath)
	if err != nil {
		utils.RespondError(w, http.StatusInternalServerError, "读取目录失败")
		return
	}

	files := make([]models.FileInfo, 0)
	for _, entry := range entries {
		info, err := entry.Info()
		if err != nil {
			continue
		}

		fileType := "file"
		if info.IsDir() {
			fileType = "folder"
		}

		filePath := pathParam
		if pathParam != "" {
			filePath = filepath.Join(pathParam, info.Name())
		} else {
			filePath = info.Name()
		}
		// 统一使用正斜杠
		filePath = strings.ReplaceAll(filePath, "\\", "/")

		fileInfo := models.FileInfo{
			Name:     info.Name(),
			Path:     filePath,
			Type:     fileType,
			Size:     info.Size(),
			Modified: info.ModTime().Format("2006-01-02 15:04:05"),
		}

		if fileType == "file" {
			fileInfo.MimeType = utils.GetFileMimeType(info.Name())
		}

		files = append(files, fileInfo)
	}

	data := models.FileListData{
		Path:  pathParam,
		Files: files,
	}

	utils.RespondSuccess(w, "获取文件列表成功", data)
}

// CreateFolder 创建文件夹
func (h *FileHandler) CreateFolder(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		utils.RespondError(w, http.StatusMethodNotAllowed, "方法不允许")
		return
	}

	var req models.CreateFolderRequest
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		utils.RespondError(w, http.StatusBadRequest, "请求参数无效")
		return
	}

	if req.Name == "" {
		utils.RespondError(w, http.StatusBadRequest, "文件夹名称不能为空")
		return
	}

	// 清理文件夹名称，防止路径遍历攻击
	safeFolderName := utils.SanitizeFilename(req.Name)
	if safeFolderName == "" {
		utils.RespondError(w, http.StatusBadRequest, "文件夹名称无效")
		return
	}

	basePath, safe := utils.SafePath(h.config.Storage.Path, req.Path)
	if !safe {
		utils.RespondError(w, http.StatusBadRequest, "无效的路径")
		return
	}

	folderPath := filepath.Join(basePath, safeFolderName)
	
	err = utils.EnsureDir(folderPath)
	if err != nil {
		utils.RespondError(w, http.StatusInternalServerError, "创建文件夹失败")
		return
	}

	utils.RespondSuccess(w, "文件夹创建成功", map[string]string{
		"name": safeFolderName,
		"path": filepath.Join(req.Path, safeFolderName),
	})
}

// DownloadFile 下载文件
func (h *FileHandler) DownloadFile(w http.ResponseWriter, r *http.Request) {
	pathParam := r.URL.Query().Get("path")
	if pathParam == "" {
		utils.RespondError(w, http.StatusBadRequest, "路径参数不能为空")
		return
	}

	filePath, safe := utils.SafePath(h.config.Storage.Path, pathParam)
	if !safe {
		utils.RespondError(w, http.StatusBadRequest, "无效的路径")
		return
	}

	// 检查文件是否存在
	info, err := os.Stat(filePath)
	if err != nil {
		utils.RespondError(w, http.StatusNotFound, "文件不存在")
		return
	}

	if info.IsDir() {
		utils.RespondError(w, http.StatusBadRequest, "不能下载文件夹")
		return
	}

	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		utils.RespondError(w, http.StatusInternalServerError, "打开文件失败")
		return
	}
	defer file.Close()

	// 设置响应头
	filename := filepath.Base(filePath)
	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))
	w.Header().Set("Content-Type", utils.GetFileMimeType(filename))
	w.Header().Set("Content-Length", strconv.FormatInt(info.Size(), 10))

	// 流式传输文件
	io.Copy(w, file)
}

// DeleteFiles 删除文件
func (h *FileHandler) DeleteFiles(w http.ResponseWriter, r *http.Request) {
	if r.Method != "DELETE" {
		utils.RespondError(w, http.StatusMethodNotAllowed, "方法不允许")
		return
	}

	var req models.DeleteFilesRequest
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		utils.RespondError(w, http.StatusBadRequest, "请求参数无效")
		return
	}

	if len(req.Paths) == 0 {
		utils.RespondError(w, http.StatusBadRequest, "没有指定要删除的文件")
		return
	}

	deletedFiles := make([]string, 0)
	failedFiles := make([]string, 0)

	for _, pathParam := range req.Paths {
		filePath, safe := utils.SafePath(h.config.Storage.Path, pathParam)
		if !safe {
			failedFiles = append(failedFiles, pathParam)
			continue
		}

		err := os.RemoveAll(filePath)
		if err != nil {
			failedFiles = append(failedFiles, pathParam)
		} else {
			deletedFiles = append(deletedFiles, pathParam)
		}
	}

	if len(deletedFiles) == 0 {
		utils.RespondError(w, http.StatusInternalServerError, "所有文件删除失败")
		return
	}

	message := fmt.Sprintf("成功删除 %d 个文件", len(deletedFiles))
	if len(failedFiles) > 0 {
		message += fmt.Sprintf("，%d 个文件删除失败", len(failedFiles))
	}

	utils.RespondSuccess(w, message, map[string]interface{}{
		"deletedFiles": deletedFiles,
		"failedFiles":  failedFiles,
	})
}

// MoveFile 移动/重命名文件
func (h *FileHandler) MoveFile(w http.ResponseWriter, r *http.Request) {
	if r.Method != "PUT" {
		utils.RespondError(w, http.StatusMethodNotAllowed, "方法不允许")
		return
	}

	var req models.MoveFileRequest
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		utils.RespondError(w, http.StatusBadRequest, "请求参数无效")
		return
	}

	if req.From == "" || req.To == "" {
		utils.RespondError(w, http.StatusBadRequest, "源路径和目标路径不能为空")
		return
	}

	fromPath, safe1 := utils.SafePath(h.config.Storage.Path, req.From)
	toPath, safe2 := utils.SafePath(h.config.Storage.Path, req.To)
	
	if !safe1 || !safe2 {
		utils.RespondError(w, http.StatusBadRequest, "无效的路径")
		return
	}

	// 检查源文件是否存在
	if _, err := os.Stat(fromPath); err != nil {
		utils.RespondError(w, http.StatusNotFound, "源文件不存在")
		return
	}

	// 确保目标目录存在
	toDir := filepath.Dir(toPath)
	err = utils.EnsureDir(toDir)
	if err != nil {
		utils.RespondError(w, http.StatusInternalServerError, "创建目标目录失败")
		return
	}

	// 移动文件
	err = os.Rename(fromPath, toPath)
	if err != nil {
		utils.RespondError(w, http.StatusInternalServerError, "移动文件失败")
		return
	}

	utils.RespondSuccess(w, "文件移动成功", map[string]string{
		"from": req.From,
		"to":   req.To,
	})
}

// GetFileInfo 获取文件信息
func (h *FileHandler) GetFileInfo(w http.ResponseWriter, r *http.Request) {
	pathParam := r.URL.Query().Get("path")
	if pathParam == "" {
		utils.RespondError(w, http.StatusBadRequest, "路径参数不能为空")
		return
	}

	filePath, safe := utils.SafePath(h.config.Storage.Path, pathParam)
	if !safe {
		utils.RespondError(w, http.StatusBadRequest, "无效的路径")
		return
	}

	info, err := os.Stat(filePath)
	if err != nil {
		utils.RespondError(w, http.StatusNotFound, "文件不存在")
		return
	}

	fileType := "file"
	if info.IsDir() {
		fileType = "folder"
	}

	fileInfo := models.FileInfo{
		Name:     info.Name(),
		Path:     pathParam,
		Type:     fileType,
		Size:     info.Size(),
		Modified: info.ModTime().Format("2006-01-02 15:04:05"),
	}

	if fileType == "file" {
		fileInfo.MimeType = utils.GetFileMimeType(info.Name())
	}

	utils.RespondSuccess(w, "获取文件信息成功", fileInfo)
} 